#include "guish.hpp"
#ifndef JOB_HPP
#define JOB_HPP
#include <pthread.h>
#include "EventManager.hpp"

class Job
{
public:
	Job(Shell *owner, int jobid, const string &cmd, int termWidth, int termHeight);
	~Job();
	void begin();
	
	void signal(string sig);
	int getRunState();
	void setRunState(int state, bool notifyClient);
	
	int waitForProcess(pid_t pid);
	void write(const char *message);
	void reportError(const char *message);
	
	void startClientWidget();
	void waitForDismissal();
	void endClientWidget();
	
	void addProcess(pid_t pid);
	void processFinished(pid_t pid, int result);
	void handleEvents();
	void sendEvent(Event *event);
	
	void handleInput(const char *input, int len);
	
	ShellState *getState();
	
	void shellExit();
	
public:
	int jobid;
	
private:
	friend void *jobThreadFunc(void *job);
	void threadMain();
	void handleEvent(Event *event);
	void finish(int result);
	
	StreamSender *outputSender;
	string command;
	ShellState *state;
	Shell *owner;
	int runState;
	
	EventManager jobEvents;
	
	pthread_t thread;
	pthread_mutex_t ptyInputLock;
	
	ExecutionEnvironment execEnv;
	PseudoTerminal *pty;
	
	set<pid_t> processesRunning;
	map<int,int> processesFinished;
	bool waitingForDismissal;
};
#define STATE_RUNNING 0
#define STATE_FINISHED 1
#define STATE_BACKGROUNDED 2

void *jobThreadFunc(void *job);

class ProcessFinishedEvent
	:public Event
{
public:
	ProcessFinishedEvent(pid_t pid, int result);
	pid_t pid;
	int result;
};

class ProcessStartedEvent
	:public Event
{
public:
	ProcessStartedEvent(pid_t pid);
	pid_t pid;
};

class JobSignalEvent
	:public Event
{
public:
	JobSignalEvent(string sig);
	string sig;
};

//////////////////////////////////////////////////////////////////////////////

class JobTerminated
	:public std::exception
{
public:
	JobTerminated(bool forceKill);
	bool forceKill;
};

#endif
